﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package net.libra.loader {
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;
    import flash.utils.*;
    
    import net.libra.loader.mission.*;

    public class LoaderAssist extends EventDispatcher implements ILoader {

        protected static var sharedObjectTempMap:Object = {};
        public static var version:String = "1.45";
        public static var NO_CACHE:uint = 0;
        protected static var isCachePanel:Boolean;
        public static var FLASH_CACHE:uint = 2;
        protected static var memoryMap:Object = {};
        public static var MEMORY_CACHE:uint = 1;
        protected static var sharedObjectMap:Object = {};

        private var _currentMission:Mission;
        private var _name:String;
        private var _queue:Array;
        private var _memory:Object;
        private var _base:String = "";
        private var _lazyMission:Object;
        private var _traceFunction:Function;
        private var _applicationDomain:ApplicationDomain;
        private var _sharedObjectTemp:Object;
        private var _currentLazyMission:Mission;
        private var _sharedObject:SharedObject;
        private var _lazyQueue:Array;

        public function LoaderAssist(name:String){
            _applicationDomain = new ApplicationDomain();
            super();
            _name = name;
            _sharedObject = getSharedObject(name);
            _sharedObjectTemp = getSharedObjectTemp(name);
            _memory = getMemory(name);
            _queue = [];
            _lazyQueue = [];
            _lazyMission = {};
        }
        protected static function getSharedObjectTemp(name:String):Object{
            var object:Object = sharedObjectTempMap[name];
            if (!(object)){
                object = (sharedObjectTempMap[name] = {});
            };
            return (object);
        }
        protected static function emptyObject(object:Object):void{
            var key:String;
            if (!(object)){
                return;
            };
            for (key in object) {
                delete object[key];
            };
        }
        protected static function getMemory(name:String):Object{
            var object:Object = memoryMap[name];
            if (!(object)){
                object = (memoryMap[name] = {});
            };
            return (object);
        }
        protected static function getSharedObject(name:String):SharedObject{
            var sharedObject:SharedObject = sharedObjectMap[name];
            if (!(sharedObject)){
                sharedObject = (sharedObjectMap[name] = SharedObject.getLocal(name, "/"));
            };
            return (sharedObject);
        }

        protected function stopCurrentMission():void{
            if (!(currentMission)){
                return;
            };
            var mission:Mission = currentMission;
            mission.abort();
            _queue.unshift(mission);
            setCurrentMission(null);
        }
        public function saveCache(mission:Mission):void{
            switch (mission.cacheType){
                case LoaderAssist.FLASH_CACHE:
                    _sharedObjectTemp[mission.name] = mission.bytes;
                    _memory[mission.name] = mission.bytes;
                    break;
                case LoaderAssist.MEMORY_CACHE:
                    _memory[mission.name] = mission.bytes;
                    break;
                case LoaderAssist.NO_CACHE:
                    break;
            };
        }
        public function get lazyMissionCount():uint{
            return (_lazyQueue.length);
        }
        public function getLazyMission(name:String):Mission{
            return (_lazyMission[name]);
        }
        public function set traceFunction(value:Function):void{
            _traceFunction = value;
        }
        private function _netStatusEvent(e:NetStatusEvent):void{
            LoaderAssist.isCachePanel = false;
            switch (e.info.code){
                case "SharedObject.Flush.Success":
                    flushCache();
                    break;
                case "SharedObject.Flush.Failed":
                default:
                    trace("[CACHE]", "用户拒绝使用缓存");
            };
            dispatchEvent(new LoadEvent(LoadEvent.HIDE_CACHE_PANEL));
        }
        public function get isNeedFlush():Boolean{
            var key:String;
            for (key in _sharedObjectTemp) {
                return (true);
            };
            return (false);
        }
        public function hasLazyMission(name:String):Boolean{
            var i:uint;
            if (((currentLazyMission) && ((currentLazyMission.name == name)))){
                return (true);
            };
            i = 0;
            while (i < _lazyQueue.length) {
                if (Mission(_lazyQueue[i]).name == name){
                    return (true);
                };
                i++;
            };
            return (false);
        }
        public function get isCachePanel():Boolean{
            return (LoaderAssist.isCachePanel);
        }
        public function get flashCacheSize():Number{
            return (_sharedObject.size);
        }
        public function hasMission(name:String):Boolean{
            var i:uint;
            if (((currentMission) && ((currentMission.name == name)))){
                return (true);
            };
            i = 0;
            while (i < _queue.length) {
                if (Mission(_queue[i]).name == name){
                    return (true);
                };
                i++;
            };
            return (false);
        }
        public function stopLazyQueue():void{
            if (!(currentLazyMission)){
                return;
            };
            stopCurrentLazyMission();
            trace("[CACHE]", "懒加载", "停止");
        }
        protected function missionHandler(event:LoadEvent):void{
            var mission:Mission;
            switch (event.type){
                case LoadEvent.MISSION_COMPLETE:
                    mission = event.mission;
                    trace("[CACHE]", "任务结束", mission.name);
                    saveCache(mission);
                    setCurrentMission(null);
                    dispatchEvent(event);
                    loadNextMisson();
                    break;
                case LoadEvent.MISSION_ERROR:
                    mission = event.mission;
                    trace("[CACHE]", "任务出错", mission.name);
                    setCurrentMission(null);
                    dispatchEvent(event);
                    loadNextMisson();
                    break;
                case LoadEvent.MISSION_START:
                case LoadEvent.MISSION_PROGRESS:
                case LoadEvent.MISSION_ABORT:
                    dispatchEvent(event);
                    break;
            };
        }
        public function set base(value:String):void{
            _base = ((value) || (""));
        }
        public function loadLazyMission(mission:Mission):void{
            if (!(mission.name)){
                trace("[CACHE]", "添加懒加载任务", "失败", "名称为空");
                return;
            };
            if (!(mission.path)){
                trace("[CACHE]", "添加懒加载任务", "失败", "路径为空");
                return;
            };
            if (((hasMission(mission.name)) || (hasLazyMission(mission.name)))){
                trace("[CACHE]", "添加懒加载任务", "失败", "已经存在", mission.name);
                return;
            };
            if (!(mission.key)){
                mission.key = "";
            };
            if (!(mission.applicationDomain)){
                mission.applicationDomain = applicationDomain;
            };
            if (!(mission.base)){
                mission.base = base;
            };
            _lazyQueue.push(mission);
            startLazyQueue();
        }
        public function get applicationDomain():ApplicationDomain{
            return (_applicationDomain);
        }
        public function get currentLazyMission():Mission{
            return (_currentLazyMission);
        }
        protected function setCurrentLazyMission(mission:Mission):void{
            if (currentLazyMission){
                currentLazyMission.removeEventListener(LoadEvent.MISSION_COMPLETE, lazyMissionHandler);
                currentLazyMission.removeEventListener(LoadEvent.MISSION_ERROR, lazyMissionHandler);
                _currentLazyMission = null;
            };
            if (!(mission)){
                return;
            };
            _currentLazyMission = mission;
            mission.addEventListener(LoadEvent.MISSION_COMPLETE, lazyMissionHandler);
            mission.addEventListener(LoadEvent.MISSION_ERROR, lazyMissionHandler);
        }
        public function getClass(def:String):Class{
            var c:* = null;
            var def:* = def;
            try {
                c = (applicationDomain.getDefinition(def) as Class);
            } catch(error:Error) {
            };
            return (c);
        }
        protected function loadNextMisson():void{
            if (currentMission){
                return;
            };
            if (missionCount < 1){
                trace("[CACHE]", "任务完成", "所有");
                dispatchEvent(new LoadEvent(LoadEvent.MISSION_EMPTY));
                startLazyQueue();
                return;
            };
            var mission:Mission = (_queue.shift() as Mission);
            trace("[CACHE]", "任务开始", mission.name);
            setCurrentMission(mission);
            if (mission.useCache){
                mission.start(getBytes(mission.name));
            } else {
                mission.start(null);
            };
        }
        public function getBytes(name:String):ByteArray{
            var bytes:ByteArray = ((_memory[name]) || (((_sharedObjectTemp[name]) || (_sharedObject.data[name]))));
            bytes = Mission.copyBytes(bytes);
            return (bytes);
        }
        public function trace(... _args):void{
            if (traceFunction != null){
                traceFunction.apply(null, _args);
            };
        }
        public function removeBytes(name:String):void{
            trace("[CACHE]", "删除缓存", name);
            delete _sharedObject.data[name];
            delete _sharedObjectTemp[name];
            delete _memory[name];
        }
        public function get traceFunction():Function{
            return (_traceFunction);
        }
        public function removeAllMission(containCurrentMission:Boolean):void{
            var mission:Mission;
            trace("[CACHE]", "移除任务", "所有");
            if (((containCurrentMission) && (currentMission))){
                currentMission.abort();
                mission = currentMission;
                setCurrentMission(null);
                dispatchEvent(new LoadEvent(LoadEvent.MISSION_REMOVE,null, 0, 0, mission));
            };
            while (_queue.length > 0) {
                mission = (_queue.pop() as Mission);
                dispatchEvent(new LoadEvent(LoadEvent.MISSION_REMOVE,null, 0, 0, mission));
            };
        }
        public function get base():String{
            return (_base);
        }
        public function get currentMission():Mission{
            return (_currentMission);
        }
        public function loadMission(mission:Mission, priorityType:uint=0):void{
            if (!(mission.name)){
                trace("[CACHE]", "添加任务", "失败", "名称为空");
                return;
            };
            if (!(mission.path)){
                trace("[CACHE]", "添加任务", "失败", "路径为空");
                return;
            };
            if (!(mission.key)){
                mission.key = "";
            };
            if (hasMission(mission.name)){
                trace("[CACHE]", "添加任务", "失败", "已经存在", mission.name);
                return;
            };
            if (!(mission.applicationDomain)){
                mission.applicationDomain = applicationDomain;
            };
            if (!(mission.base)){
                mission.base = base;
            };
            switch (priorityType){
                case 2:
                    stopCurrentMission();
                    _queue.unshift(mission);
                    break;
                case 1:
                    _queue.unshift(mission);
                    break;
                case 0:
                    _queue.push(mission);
                    break;
            };
            stopLazyQueue();
            loadNextMisson();
        }
        protected function setCurrentMission(mission:Mission):void{
            if (currentMission){
                currentMission.removeEventListener(LoadEvent.MISSION_START, missionHandler);
                currentMission.removeEventListener(LoadEvent.MISSION_PROGRESS, missionHandler);
                currentMission.removeEventListener(LoadEvent.MISSION_COMPLETE, missionHandler);
                currentMission.removeEventListener(LoadEvent.MISSION_ERROR, missionHandler);
                currentMission.removeEventListener(LoadEvent.MISSION_ABORT, missionHandler);
                _currentMission = null;
            };
            if (!(mission)){
                return;
            };
            _currentMission = mission;
            mission.addEventListener(LoadEvent.MISSION_START, missionHandler);
            mission.addEventListener(LoadEvent.MISSION_PROGRESS, missionHandler);
            mission.addEventListener(LoadEvent.MISSION_COMPLETE, missionHandler);
            mission.addEventListener(LoadEvent.MISSION_ERROR, missionHandler);
            mission.addEventListener(LoadEvent.MISSION_ABORT, missionHandler);
        }
        protected function lazyMissionHandler(event:LoadEvent):void{
            var _local2:Mission;
            switch (event.type){
                case LoadEvent.MISSION_COMPLETE:
                    _local2 = event.mission;
                    saveCache(_local2);
                    _lazyMission[_local2.name] = _local2;
                    setCurrentLazyMission(null);
                    loadNextLazyMission();
                    break;
                case LoadEvent.MISSION_ERROR:
                    setCurrentLazyMission(null);
                    loadNextLazyMission();
                    break;
            };
        }
        public function createObject(def:String):Object{
            var c:Class = getClass(def);
            return ((c) ? new (c)() : null);
        }
        public function get missionCount():uint{
            return (_queue.length);
        }
        public function flushCache():void{
            var fs:* = null;
            if (!(isNeedFlush)){
                return;
            };
            if (isCachePanel){
                return;
            };
            trace("[CACHE]", "FLUSH!");
            try {
                fs = _sharedObject.flush(((0x0400 * 0x0400) * 100));
            } catch(err:Error) {
            };
            if (fs == SharedObjectFlushStatus.PENDING){
                _sharedObject.addEventListener(NetStatusEvent.NET_STATUS, _netStatusEvent);
                LoaderAssist.isCachePanel = true;
                dispatchEvent(new LoadEvent(LoadEvent.SHOW_CACHE_PANEL));
            } else {
                if (fs == SharedObjectFlushStatus.FLUSHED){
                    transferCache();
                    emptyObject(_sharedObjectTemp);
                    _sharedObject.flush(((0x0400 * 0x0400) * 100));
                } else {
                    if (!(fs)){
                        dispatchEvent(new LoadEvent(LoadEvent.DISABLED_CACHE));
                    };
                };
            };
        }
        public function transferCache():void{
            var i:String;
            for (i in _sharedObjectTemp) {
                _sharedObject.data[i] = _sharedObjectTemp[i];
            };
        }
        public function set applicationDomain(value:ApplicationDomain):void{
            _applicationDomain = ((value) || (new ApplicationDomain()));
        }
        protected function loadNextLazyMission():void{
            if (currentMission){
                return;
            };
            if (currentLazyMission){
                return;
            };
            if (lazyMissionCount < 1){
                trace("[CACHE]", "懒加载", "所有任务已完成");
                dispatchEvent(new LoadEvent(LoadEvent.LAZY_MISSION_EMPTY));
                return;
            };
            var mission:Mission = (_lazyQueue.shift() as Mission);
            trace("[CACHE]", "懒加载", "开始", mission.name);
            setCurrentLazyMission(mission);
            if (mission.useCache){
                mission.start(getBytes(mission.name));
            } else {
                mission.start(null);
            };
        }
        public function removeAllBytes():void{
            trace("[CACHE]", "删除缓存", "所有");
            emptyObject(_memory);
            emptyObject(_sharedObjectTemp);
            emptyObject(_sharedObject.data);
        }
        protected function stopCurrentLazyMission():void{
            if (!(currentLazyMission)){
                return;
            };
            var mission:Mission = currentLazyMission;
            mission.abort();
            _lazyQueue.unshift(mission);
            setCurrentLazyMission(null);
        }
        public function startLazyQueue():void{
            if (lazyMissionCount < 1){
                return;
            };
            if (currentMission){
                return;
            };
            if (currentLazyMission){
                return;
            };
            trace("[CACHE]", "懒加载", "开始");
            loadNextLazyMission();
        }
        public function removeMission(name:String, containCurrentMission:Boolean):void{
            var i:uint;
            var mission:Mission;
            if (!(name)){
                return;
            };
            trace("[CACHE]", "移除任务", name);
            i = 0;
            while (i < _queue.length) {
                if (Mission(_queue[i]).name == name){
                    mission = (_queue.splice(i, 1)[0] as Mission);
                    dispatchEvent(new LoadEvent(LoadEvent.MISSION_REMOVE,null, 0, 0, mission));
                    return;
                };
                i++;
            };
            if (((((containCurrentMission) && (currentMission))) && ((currentMission.name == name)))){
                mission = currentMission;
                currentMission.abort();
                setCurrentMission(null);
                dispatchEvent(new LoadEvent(LoadEvent.MISSION_REMOVE,null, 0, 0, mission));
                loadNextMisson();
            };
        }
        public function hasBytes(name:String):Boolean{
            return (!((getBytes(name) == null)));
        }

    }
}//package net.l4cd.loader 
